package com.vizhuo.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 专门用于处理日期的工具类
 * 
 * @author
 * 
 */
public class DateUtil {
    private static Logger log = LoggerFactory.getLogger(DateUtil.class);

    /**
     * 为一个日期增加对应的时间，减的话amount传入负数即可
     * 
     * @param date
     *            增加前的日期
     * @param field
     *            需要增加的时间类型（年、月、日等，具体应用时可直接使用addYear(),addMonth()等）
     * @param amount
     *            需要增加的数字
     * @return
     */
    public static Date add(Date date, int field, int amount) {
        Calendar c = getCalendarForDate(date);
        c.add(field, amount);
        return c.getTime();
    }

    /**
     * 将Date转换为Calendar类型
     * 
     * @param date
     * @return
     */
    public static Calendar getCalendarForDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c;
    }

    /**
     * 为一个日期增加对应的年份
     * 
     * @param date
     * @param year
     * @return
     */
    public static Date addYear(Date date, int year) {
        return add(date, Calendar.YEAR, year);
    }

    /**
     * 为一个日期增加对应的小时
     * 
     * @param date
     * @param year
     * @return
     */
    public static Date addHour(Date date, int hour) {
        return add(date, Calendar.HOUR_OF_DAY, hour);
    }

    /**
     * 为一个日期增加对应的分钟
     * 
     * @param date
     * @param year
     * @return
     */
    public static Date addMinute(Date date, int minute) {
        return add(date, Calendar.MINUTE, minute);
    }

    /**
     * 为一个日期增加对应的月份
     * 
     * @param date
     * @param month
     * @return
     */
    public static Date addMonth(Date date, int month) {
        return add(date, Calendar.MONTH, month);
    }

    /**
     * 为一个日期增加对应的天数
     * 
     * @param date
     * @param day
     * @return
     */
    public static Date addDay(Date date, int day) {
        return add(date, Calendar.DAY_OF_MONTH, day);
    }

    /**
     * 获得date所处季度的最后一个月的最后一天
     * 
     * @param date
     * @return
     */
    public static Date getLastDayOfQuarter(Date date) {
        Calendar c = getCalendarForDate(date);
        int quarter = getQuarter(date);
        int lastMonthOfQuarter = getLastMonthOfQuarter(quarter);
        c.set(Calendar.MONTH, lastMonthOfQuarter);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        return c.getTime();
    }

    /**
     * 获取quarter季度的最后一个月，0表示1月、1表示2月，以此类推
     * 
     * @param quarter
     * @return
     */
    public static int getLastMonthOfQuarter(int quarter) {
        return quarter * 3 - 1;
    }

    /**
     * 获取date所属的季度
     * 
     * @param date
     * @return
     */
    public static int getQuarter(Date date) {
        Calendar c = getCalendarForDate(date);
        int month = c.get(Calendar.MONTH);
        return month / 3 + 1;
    }

    /**
     * 将Date转换为String类型
     * 
     * @param d
     * @param format
     *            格式化字符串
     * @return
     */
    public static String date2String(Date d, String format) {
        if (d == null)
            return "";
        DateFormat df = new SimpleDateFormat(format);
        return df.format(d);
    }

    /**
     * 将java.sql.Time转换为String类型,采用默认格式转换HH:mm:ss
     * 
     * @param d
     * @param format
     *            格式化字符串
     * @return
     */
    public static String time2String(java.sql.Time d) {
        return time2String(d, "HH:mm:ss");
    }

    /**
     * 将java.sql.Time转换为String类型
     * 
     * @param d
     * @param format
     *            格式化字符串
     * @return
     */
    public static String time2String(java.sql.Time d, String format) {
        if (d == null)
            return "";
        DateFormat df = new SimpleDateFormat(format);
        return df.format(d);
    }

    /**
     * 将Date转换为String类型 采用默认格式转换yyyy-MM-dd HH:mm:ss
     * 
     * @param d
     * @return
     */
    public static String date2String(Date d) {
        return date2String(d, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将Date转换为String类型 采用默认格式转换yyyy-MM-dd,不含时分秒
     * 
     * @param d
     * @return
     */
    public static String date2StringNoTime(Date d) {
        return date2String(d, "yyyy-MM-dd");
    }

    /**
     * 将String转换为Date类型
     * 
     * @param str
     * @param format
     * @return
     */
    public static Date string2Date(String str, String format) {
        DateFormat df = new SimpleDateFormat(format);
        try {
            return df.parse(str);
        } catch (ParseException e) {
            log.error("日期转换出错！", e);
            return null;
        }
    }

    /**
     * 将String转换为java.sql.Time类型 采用默认格式转换HH:mm:ss
     * 
     * @param str
     * @return
     * @throws ParseException
     */
    public static java.sql.Time string2Time(String str) {
        return string2Time(str, "HH:mm:ss");
    }

    /**
     * 将String转换为java.sql.Time类型
     * 
     * @param str
     * @param format
     * @return
     */
    public static java.sql.Time string2Time(String str, String format) {
        DateFormat df = new SimpleDateFormat(format);
        try {
            return new java.sql.Time(df.parse(str).getTime());
        } catch (ParseException e) {
            log.error("日期转换出错！", e);
            return null;
        }
    }

    /**
     * 将String转换为Date类型 采用默认格式转换yyyy-MM-dd HH:mm:ss
     * 
     * @param str
     * @return
     * @throws ParseException
     */
    public static Date string2Date(String str) {
        return string2Date(str, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将String转换为Date，只有日期没有时间：yyyy-MM-dd
     * 
     * @param str
     * @return
     * @throws ParseException
     */
    public static Date string2DateNoTime(String str) {
        return string2Date(str, "yyyy-MM-dd");
    }

    /**
     * 获得当前日期的组成的字符串，格式：yyyyMMddHHmmssS
     * 
     * @return
     */
    public static String getNowStr() {
        return date2String(new Date(), "yyyyMMddHHmmssS");
    }

    /**
     * 将Timestamp转换为Date类型
     * 
     * @param timeStamp
     * @return
     */
    public static Date timestamp2Date(Timestamp timeStamp) {
        if (timeStamp == null) {
            return null;
        } else {
            long time = timeStamp.getTime();
            return new Date(time);
        }
    }

    /**
     * 判断当前时间是否处于两个时间之间
     * 
     * @param begin
     *            起始时间
     * @param end
     *            结束时间
     * @return
     */
    public static boolean nowIsBetweenDates(Date begin, Date end) {
        return isBetweenDates(new Date(), begin, end);
    }

    /**
     * 判断date是否处于begin和end之间
     * 
     * @param date
     * @param begin
     *            起始时间
     * @param end
     *            结束时间
     * @return
     */
    public static boolean isBetweenDates(Date date, Date begin, Date end) {
        return (date.after(begin) || date.equals(begin)) && (date.before(addDay(end, 1)) || date.equals(end));
    }

    /**
     * 获取当天日期,格式:yyyy-MM-dd
     * 
     * @param d
     * @param format
     *            格式化字符串
     * @return
     */
    public static String getCurrentDate() {
        Date d = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(d);
    }

    /**
     * 获取当前日期,格式:yyyy-MM-dd HH:mm:ss
     * 
     * @param d
     * @param format
     *            格式化字符串
     * @return
     */
    public static String getCurrentDateTime() {
        Date d = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(d);
    }

    /**
     * 获得两个时间之间相差的分钟数或小时数
     * 
     * @param startTime
     *            时间参数1（开始时间）
     * @param endTime时间参数2
     *            （结束时间）
     * @param str
     *            返回的类型（h：小时数，m：分钟数）
     * @return 小时数或者分钟数（整数）
     * @throws ParseException
     */
    public static Long dateDiff(Date startTime, Date endTime, String str) throws ParseException {
        long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
        long nh = 1000 * 60 * 60;// 一小时的毫秒数
        long nm = 1000 * 60;// 一分钟的毫秒数
        long ns = 1000;// 一秒钟的毫秒数long diff;try {
        // 获得两个时间的毫秒时间差异

        long diff = endTime.getTime() - startTime.getTime();
        long day = diff / nd;// 计算差多少天
        long hour = diff % nd / nh;// 计算差多少小时
        long min = diff % nd % nh / nm;// 计算差多少分钟
        long sec = diff % nd % nh % nm / ns;// 计算差多少秒//输出结果
        // System.out.println("时间相差："+day+"天"+hour+"小时"+min+"分钟"+sec+"秒。");
        // System.out.println("总分钟数："+diff/1000/60);
        // System.out.println("总小时数："+diff/1000/60/60);
        // System.out.println("总天数："+diff/1000/60/60/24);
        if (str.equals("h")) {
            return diff / 1000 / 60 / 60;
        } else if (str.equals("m")) {
            return diff / 1000 / 60;
        } else {
            throw new RuntimeException("parm str is error");
        }
    }

    /**
     * 判断两个日期是否为同一天
     * 
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isSameDay(Date date1, Date date2) {
        String dstr1 = date2String(date1, "yyyyMMdd");
        String dstr2 = date2String(date2, "yyyyMMdd");
        return dstr1.equals(dstr2);
    }

    /**
     * 获取当前unix时间戳
     * 
     * @param
     * @return
     */
    public static Long getUnixTimeStamp() {
        // 获取当前时间戳
        Long seconds = System.currentTimeMillis() / 1000L;
        return seconds;
    }

    /**
     * 获取某个时间的unix时间戳
     * 
     * @param
     * @return
     */
    public static Long getUnixTimeStamp(Date date) {
        // 获取当前时间戳
        Long seconds = date.getTime();
        return seconds;
    }

    /**
     * 得到某年某周的第一天
     * 
     * @param year
     * @param week
     * @return
     */
    public static String getFirstDayOfWeek(int year, int week) {
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置周
        cal.set(Calendar.WEEK_OF_YEAR, week);
        // 设置该周第一天为星期一
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDayOfWeek = sdf.format(cal.getTime());
        return firstDayOfWeek;
    }

    /**
     * 得到某年某周的最后一天
     * 
     * @param year
     * @param week
     * @return
     */
    public static String getLastDayOfWeek(int year, int week) {
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置周
        cal.set(Calendar.WEEK_OF_YEAR, week);
        // 设置该周第一天为星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 设置最后一天是星期日
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek() + 6); // Sunday
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayOfWeek = sdf.format(cal.getTime());
        return lastDayOfWeek;
    }

    /**
     * 以本周为准获得其他周的周一到周日中某天的日期
     * 
     * @param args
     */

    public static String getDateOfWeek(int n, int m) {
        Calendar cal = Calendar.getInstance();
        // n为推迟的周数，1本周，-1向前推迟一周，2下周，依次类推,上周周一:n=-1,m=2;上周周日:n=0,m=1;上上周周一：n=-2,m=2;上上周周日:n=-1,m=1
        // 日 一 二 三 四 五 六
        // 1 2 3 4 5 6 7(m的值)
        // int n = -1;
        String date;
        cal.add(Calendar.DATE, n * 7);
        // 想周几，这里就传几Calendar.MONDAY（TUESDAY...）
        cal.set(Calendar.DAY_OF_WEEK, m);
        date = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
        return date;
    }

    /**
     * 获得今天以前某天的日期(昨天n=-1，前天n=-2依次类推)
     * 
     * @param args
     */

    public static String getDateBeforeToday(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, n);
        String date = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
        return date;
    }

    /**
     * 获得今天以前某天的日期(昨天n=-1，前天n=-2依次类推)的到的值形如:12.20
     * 
     * @param args
     */

    public static String getDateBeforeTodayByDot(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, n);
        String date = new SimpleDateFormat("MM.dd").format(calendar.getTime());
        return date;
    }

    public static void main(String[] args) {

        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, 2015);
        // 设置周
        cal.set(Calendar.WEEK_OF_YEAR, 37);
        // 设置该周第一天为星期一
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDayOfWeek = sdf.format(cal.getTime());
        System.out.println("2015" + "年第" + 37 + "个礼拜的第一天是" + firstDayOfWeek);
    }
}
